package com.chkj.fbook.system.service.impl;

import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import javax.annotation.Resource;
import javax.imageio.ImageIO;

import com.chkj.fbook.system.service.DeptService;
import com.chkj.fbook.system.service.UserService;
import org.apache.commons.lang.ArrayUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.chkj.fbook.common.config.HpcarConfig;
import com.chkj.fbook.common.domain.FileDO;
import com.chkj.fbook.common.domain.Tree;
import com.chkj.fbook.common.service.FileService;
import com.chkj.fbook.common.utils.BuildTree;
import com.chkj.fbook.common.utils.FileType;
import com.chkj.fbook.common.utils.FileUtil;
import com.chkj.fbook.common.utils.IDUtils;
import com.chkj.fbook.common.utils.ImageUtils;
import com.chkj.fbook.common.utils.MD5Utils;
import com.chkj.fbook.common.utils.StringUtils;
import com.chkj.fbook.system.dao.DeptDao;
import com.chkj.fbook.system.dao.UserDao;
import com.chkj.fbook.system.dao.UserRoleDao;
import com.chkj.fbook.system.domain.DeptDO;
import com.chkj.fbook.system.domain.UserDO;
import com.chkj.fbook.system.domain.UserRoleDO;
import com.chkj.fbook.system.vo.UserVO;

@Transactional
@Service
public class UserServiceImpl implements UserService {

	private static final Logger logger = LoggerFactory.getLogger(UserService.class);

	@Resource
	private UserDao userMapper;
	@Resource
	private UserRoleDao userRoleMapper;
	@Resource
	private DeptDao deptMapper;
	@Autowired
	private FileService sysFileService;
	@Autowired
	private HpcarConfig hpcarConfig;
	@Autowired
    DeptService deptService;

	@Override
	public UserDO get(String id) {
		List<String> roleIds = userRoleMapper.listRoleId(id);
		UserDO user = userMapper.get(id);
		DeptDO deptDO = deptMapper.get(user.getDeptId());
		if(deptDO!=null) {
			user.setDeptName(deptDO.getName());
		}
		user.setRoleIds(roleIds);
		return user;
	}

	@Override
	public List<UserDO> list(Map<String, Object> map) {
		String deptId = map.get("deptId").toString();
		if (StringUtils.isNotBlank(deptId)) {
			List<String> childIds = deptService.listChildrenIds(deptId);
			childIds.add(deptId);
			map.put("deptId", null);
			map.put("deptIds", childIds);
		}
		return userMapper.list(map);
	}

	@Override
	public int count(Map<String, Object> map) {
		return userMapper.count(map);
	}

	@Transactional
	@Override
	public int save(UserDO user) {

		user.setUserId(IDUtils.genUUID());
		user.setGmtCreate(new Date());
		user.setGmtModified(new Date());

		int count = userMapper.save(user);
		String userId = user.getUserId();
		List<String> roles = user.getRoleIds();
		userRoleMapper.removeByUserId(userId);
		List<UserRoleDO> list = new ArrayList<>();
		for (String roleId : roles) {
			UserRoleDO ur = new UserRoleDO();
			ur.setId(IDUtils.genUUID());
			ur.setUserId(userId);
			ur.setRoleId(roleId);
			list.add(ur);
		}
		if (list.size() > 0) {
			userRoleMapper.batchSave(list);
		}
		return count;
	}

	@Override
	public int update(UserDO user) {

		user.setGmtModified(new Date());

		int r = userMapper.update(user);
		String userId = user.getUserId();
		List<String> roles = user.getRoleIds();
		userRoleMapper.removeByUserId(userId);
		List<UserRoleDO> list = new ArrayList<>();
		for (String roleId : roles) {
			UserRoleDO ur = new UserRoleDO();
			ur.setId(IDUtils.genUUID());
			ur.setUserId(userId);
			ur.setRoleId(roleId);
			list.add(ur);
		}
		if (list.size() > 0) {
			userRoleMapper.batchSave(list);
		}
		return r;
	}

	// @CacheEvict(value = "user")
	@Override
	public int remove(String userId) {
		userRoleMapper.removeByUserId(userId);
		return userMapper.remove(userId);
	}

	@Override
	public boolean exit(Map<String, Object> params) {
		boolean exit;
		exit = userMapper.list(params).size() > 0;
		return exit;
	}

	@Override
	public Set<String> listRoles(String userId) {
		return null;
	}

	@Override
	public int resetPwd(UserVO userVO, UserDO userDO) throws Exception {
		if (Objects.equals(userVO.getUserDO().getUserId(), userDO.getUserId())) {
			if (Objects.equals(MD5Utils.encryptPassword(MD5Utils.md5(userVO.getPwdOld())), userDO.getPassword())) {
				userDO.setPassword(MD5Utils.encryptPassword(MD5Utils.md5(userVO.getPwdNew())));
				return userMapper.update(userDO);
			} else {
				throw new Exception("输入的旧密码有误！");
			}
		} else {
			throw new Exception("你修改的不是你登录的账号！");
		}
	}

	@Override
	public int adminResetPwd(UserVO userVO) throws Exception {
		UserDO userDO = get(userVO.getUserDO().getUserId());
		if ("admin".equals(userDO.getUsername())) {
			throw new Exception("超级管理员的账号不允许直接重置！");
		}
		userDO.setPassword(MD5Utils.encryptPassword(MD5Utils.md5(userVO.getPwdNew())));
		return userMapper.update(userDO);

	}

	@Transactional
	@Override
	public int batchremove(String[] userIds) {
		int count = userMapper.batchRemove(userIds);
		userRoleMapper.batchRemoveByUserId(userIds);
		return count;
	}

	@Override
	public Tree<DeptDO> getTree() {
		List<Tree<DeptDO>> trees = new ArrayList<Tree<DeptDO>>();
		List<DeptDO> depts = deptMapper.list(new HashMap<String, Object>(16));
		String[] pDepts = deptMapper.listParentDept();
		String[] uDepts = userMapper.listAllDept();
		String[] allDepts = (String[]) ArrayUtils.addAll(pDepts, uDepts);
		for (DeptDO dept : depts) {
			if (!ArrayUtils.contains(allDepts, dept.getDeptId())) {
				continue;
			}
			Tree<DeptDO> tree = new Tree<DeptDO>();
			tree.setId(dept.getDeptId().toString());
			tree.setParentId(dept.getParentId().toString());
			tree.setText(dept.getName());
			Map<String, Object> state = new HashMap<>(16);
			state.put("opened", true);
			state.put("mType", "dept");
			tree.setState(state);
			trees.add(tree);
		}
		List<UserDO> users = userMapper.list(new HashMap<String, Object>(16));
		for (UserDO user : users) {
			Tree<DeptDO> tree = new Tree<DeptDO>();
			tree.setId(user.getUserId().toString());
			tree.setParentId(user.getDeptId().toString());
			tree.setText(user.getName());
			Map<String, Object> state = new HashMap<>(16);
			state.put("opened", true);
			state.put("mType", "user");
			tree.setState(state);
			trees.add(tree);
		}
		// 默认顶级菜单为０，根据数据库实际情况调整
		Tree<DeptDO> t = BuildTree.build(trees);
		return t;
	}

	@Override
	public int updatePersonal(UserDO userDO) {
		return userMapper.update(userDO);
	}

	@Override
	public Map<String, Object> updatePersonalImg(MultipartFile file, String avatar_data, String userId)
			throws Exception {
		String fileName = file.getOriginalFilename();
		fileName = FileUtil.renameToUUID(fileName);
		FileDO sysFile = new FileDO(FileType.fileType(fileName), "/files/" + fileName, new Date());
		// 获取图片后缀
		String prefix = fileName.substring((fileName.lastIndexOf(".") + 1));
		String[] str = avatar_data.split(",");
		// 获取截取的x坐标
		int x = (int) Math.floor(Double.parseDouble(str[0].split(":")[1]));
		// 获取截取的y坐标
		int y = (int) Math.floor(Double.parseDouble(str[1].split(":")[1]));
		// 获取截取的高度
		int h = (int) Math.floor(Double.parseDouble(str[2].split(":")[1]));
		// 获取截取的宽度
		int w = (int) Math.floor(Double.parseDouble(str[3].split(":")[1]));
		// 获取旋转的角度
		int r = Integer.parseInt(str[4].split(":")[1].replaceAll("}", ""));
		try {
			BufferedImage cutImage = ImageUtils.cutImage(file, x, y, w, h, prefix);
			BufferedImage rotateImage = ImageUtils.rotateImage(cutImage, r);
			ByteArrayOutputStream out = new ByteArrayOutputStream();
			boolean flag = ImageIO.write(rotateImage, prefix, out);
			// 转换后存入数据库
			byte[] b = out.toByteArray();
			FileUtil.uploadFile(b, hpcarConfig.getUploadPath(), fileName);
		} catch (Exception e) {
			throw new Exception("图片裁剪错误！！");
		}
		Map<String, Object> result = new HashMap<>();
		if (sysFileService.save(sysFile) > 0) {
			UserDO userDO = new UserDO();
			userDO.setUserId(userId);
			userDO.setPicId(sysFile.getId());
			if (userMapper.update(userDO) > 0) {
				result.put("url", sysFile.getUrl());
			}
		}
		return result;
	}

	@Override
	public UserDO getByUserName(String username) {
		return userMapper.getByUserName(username);
	}

	@Override
	public String rpcResetPwd(Map<String, String> map, UserDO UserDO) {

		if (Objects.equals(map.get("userId"), UserDO.getUserId())) {
			if (Objects.equals(MD5Utils.encryptPassword(MD5Utils.md5(map.get("pwdOld"))), UserDO.getPassword())) {
				UserDO.setPassword(MD5Utils.encryptPassword(MD5Utils.md5(map.get("pwdNew"))));
				
				UserDO userDO = new UserDO();
				try {
					BeanUtils.copyProperties(userDO, UserDO);
				} catch (Exception e) {}
				userMapper.update(userDO);
				return "0";//表示成功
			} else {
				return "输入的旧密码有误！";
			}
		} else {
			return "你修改的不是你登录的账号！";
		}

	}

}
